package thread.sync;

import thread.invariantframework.Invariant;
import thread.invariantframework.InvariantWatcher;
import thread.invariantframework.state.InvariantFailure;
import thread.invariantframework.state.InvariantOK;
import thread.invariantframework.state.InvariantState;

public class UnproperResourceVisit {

	public static void main(String[] args) {
		final Resource resource = new Resource();
		// 1.新建一个线程用于对资源不停“查”
		new Thread("Watcher") {
			@Override
			public void run() {
				while(true) {
					int val = resource.getValue();
					if(val % 2 != 0) {
						System.out.println(val);
						System.exit(0);
					}
				}
			}
		}.start();
		
		// 2.主线程开始对资源不断“写”
		while(true) {
			resource.next();
		}
	}
}

class Resource {

	private int i = 0;
	
	public void next() {
		i++;
		i++;
	}
	
	public int getValue() {
		return i;
	}
}

// 通过invariant()把“查”的功能封装起来
class Resource2 implements Invariant {
	private int i;

	public void next() {
		i++;
		i++;
	}

	public int getValue() {
		return i;
	}

	public InvariantState invariant() {
		int val = i; // Capture it in case it changes （必须把所有相关的值都存放到局部变量中。这样，你才能返回你真正测试的那个值，否则在返回的时候这个值可能已经（被别的线程）改变）
		if (val % 2 == 0)
			return new InvariantOK();
		else
			return new InvariantFailure(new Integer(val));
	}

	public static void main(String[] args) {
		Resource2 r2 = new Resource2();
		new InvariantWatcher(r2);
		while (true)
			r2.next();
	}
}
